package js.dwim.server;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.List;

import js.dwim.domain.CommSession;
import js.dwim.domain.Command;
import js.dwim.domain.MapNode;
import js.dwim.domain.Player;
import js.dwim.domain.Command.Type;
import js.dwim.domain.WorldMap;
import js.dwim.web.XmppCommServlet;

public class CommandInterpreter
{
    private CommandInterpreter()
    {
    }

    public static void process( CommSession session, String msg )
    {
        Command cmd     = new Command( msg );
        String reply    = "";
        boolean valid   = false;

        try
        {
            switch ( cmd.getType() )
            {
                case Help:
                {
                    valid = true;
                    reply = "List of supported commands: ";
    
                    for ( Command.Type t : Command.Type.values() )
                    {
                        if ( t == Type.Unknown )
                            continue;
    
                        reply += "\n" + Command.KEYWORDS.get( t );
                    }
                    reply += "\n";
                    break;
                }
                case PlayerInfo:
                {
                    Player player = session.getPlayer();
    
                    valid = true;
                    reply = String.format( "NAME:%s\nACTIVE:%s\nSESSION_START:%s\nLAST_ACTIVE:%s\nJID:%s\n",
                            player.getName(),
                            session.isActive(),
                            session.getStartDate(),
                            session.getLastActivityDate(),
                            session.getJid() );
                    break;
                }
                case PlayerChangeName:
                {
                    String name = cmd.getArgs().trim();
                    if ( name.isEmpty() || name.equals( Player.AI_PLAYER ) )
                    {
                    	reply = "Invalid name specified";
                    	break;
                    }
                    session.getPlayer().setName( name );
    
                    valid = true;
                    reply = String.format( "NAME:%s\n", name );
                    break;
                }
                case CloseSession:
                {
                    WorldMap world 	= Game.getWorldMap();
                    Player player 	= session.getPlayer();
                    world.removePlayer( player );
                    player.setFunds( 0 );
                    session.setActive( false );
                    Persistence.store( player );
                    Persistence.store( world );
                
                    valid = true;
                    reply = "TERMINATED\n";
                    break;
                }
                case DebugWipeAll:
                {
                    WorldMap world = Game.getWorldMap();
                    world.reset();
                    Persistence.store( world );
                    //Persistence.deleteAllPersistent();
    
                    valid = true;
                    reply = "WIPED\n";
                    break;
                }
                case GetServerTime:
                {
                    valid = true;
                    reply = String.format( "TIME:%s\n", new Date() );
                    break;
                }
                case GameStats:
                {
                	Player player 		= session.getPlayer();
                    List<MapNode> nodes = Game.getWorldMap().getPlayerNodes( player );
      
                    valid = true;
                    reply = String.format( "NODE_COUNT:%s\nFUNDS:%s\n", 
                    		nodes.size(),
                    		player.getFunds() );
                    break;
                }
                case Scoreboard:
                {
                	List<MapNode> nodes = Game.getWorldMap().getNodes();
                	String nodeInfo 	= "";
                	for ( MapNode node: nodes )
                	{
                		nodeInfo += String.format( "KEY:%s\nPLAYER:%s\nX:%s\nY:%s\n",
                				node.getKey(),
                				node.getPlayer().getName(),
                				node.getLocation().getX(),
                				node.getLocation().getY() );
                	}                	
                	valid = true;
                    reply = String.format( "TOTAL_NODES:%s\n%s",
                    		nodes.size(),
                    		nodeInfo );
                    break;
                }
                case GameRequest:
                {
                    try
                    {
                        WorldMap world = Game.getWorldMap();
                        world.addPlayer( session.getPlayer() );
                        session.setActive( true );
                        Persistence.store( world );
                        
                        valid = true;
                        reply = "ACTIVATED\n";
                    }
                    catch ( GameLogicException e )
                    {
                        reply = e.getMessage();
                    }
                    break;
                }
                default:
                    reply = String.format( "Unknown command: %s\n", msg );
            }
        }
        catch( Exception ex )
        {
        	StringWriter sw = new StringWriter();
        	PrintWriter pw 	= new PrintWriter( sw );
        	
        	ex.printStackTrace(pw);
        	
            reply = String.format( "Unhandled exception: %s\nMessage: %s\nTrace: %s\nCause: %s\n",
            		ex.getClass().toString(),
                    ex.getMessage(),
                    sw.toString(),
                    ex.getCause() );
        }
        finally
        {
            XmppCommServlet.sendMessage( session, ( valid ? "OK\n" : "ERR\n" ) + reply );
        }
    }
}
